
"""

Auto tag message using various rules
"""

import re

class RuleParser:
    def __init__ (self, filename):
        fp = None
        self.rule = []
        try:
            fp = open(filename)
            self.rule = self.parseDo(fp)
        finally:
            if (fp): fp.close()

    # The Parser ===================================
    def parseCmd (self, fp, ls):
        if ((ls[0].upper() == 'MATCH') or
            (ls[0].upper() == '!MATCH')):
            return self.parseMatch(fp, ls[0])        
        else:
            return ls

    def parseDo (self, fp):
        output = []
        while (True):
            s = fp.readline()
            if (not s): break            
            ls = s.split()
            if (len(ls) == 0): continue
            if (ls[0][0] == '#'): continue      # Comment line
            if (ls[0].upper() == 'END'): break
            output.append(self.parseCmd(fp, ls))
        return output

    def parseMatch (self, fp, name):
        matchList = []
        while (True):
            s = fp.readline()
            if (not s): raise Exception, 'Rule file not complete'
            ls = s.split()
            if (len(ls) == 0): continue
            if (ls[0][0] == '#'): continue      # Comment line
            if (ls[0].upper() == 'DO'):
                action = self.parseDo(fp)
                break            
            # The rule
            matchList.append((re.compile(ls[0], re.I | re.M), ls[1:]))
        return (name, matchList, action)

    # The Interpreter ======================================

    def doMatch (self, header, tagPool, name, matchList, actionList):
        isMatched = False
        for pattern, tryHeaders in matchList:
            for tryHeader in tryHeaders:
                value = header.get(tryHeader.upper())
                if (not value): continue
                if (pattern.search(value)):
                    isMatched = True
                    break
            if (name[0] == '!'): isMatched = (not isMatched)
            if (isMatched): break
        if (isMatched):
            return self.doList(header, tagPool, actionList)
    
    def doList (self, header, tagPool, actionList):
        for action in actionList:
            if ((action[0].upper() == 'MATCH') or
                (action[0].upper() == '!MATCH')):
                ret = self.doMatch(header, tagPool,
                                   action[0], action[1], action[2])
                if (ret == 'STOP'): return 'STOP'
            elif (action[0].upper() == 'TAG'):
                for tag in action[1:]:
                    tagPool[tag] = True
            elif (action[0].upper() == 'UNTAG'):
                for tag in action[1:]:
                    if (tagPool.get(tag)): del(tagPool[tag])
            elif (action[0].upper() == 'STOP'):
                return 'STOP'

    def run (self, header, tagPool):
        return self.doList(header, tagPool, self.rule)

class AutoTagger:
    def __init__ (self, confFile):
        self.loadConf(confFile)

    def loadConf(self, confFile):
        self.parser = RuleParser(confFile)

    def tag (self, headers, tagPool):
        self.parser.run(headers, tagPool)
        if (len(tagPool) == 0):
            tagPool['Inbox'] = True
        tagPool['-'] = True
        return True               
            
if __name__ == '__main__':
    import sys
    parser = RuleParser ('test.rule')
    print 'Input headers'
    headers = {}
    tags = {}
    while (True):
        s = sys.stdin.readline().strip()
        if (not s): break

        header, value = s.split(None, 1)
        headers[header.upper()] = value

    parser.run(headers, tags)
    print tags.keys()


    
